# new Vue 发生了什么

# 通过 new 实例化 Vue

  • /src/core/instance/index.js
function Vue (options) {
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}
1
2
3
4
5
6
7
8

# this._init()

  • /src/core/instance/init.js
  • 合并配置,初始化生命周期,初始化事件中心,初始化渲染,初始化 data、props、computed、watcher 等。
  • vm.$options = options
  • vm.$mount 挂载 vm
export function initMixin (Vue: Class<Component>) {
  Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    // a uid
    vm._uid = uid++

    let startTag, endTag
    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      startTag = `vue-perf-start:${vm._uid}`
      endTag = `vue-perf-end:${vm._uid}`
      mark(startTag)
    }

    // a flag to avoid this being observed
    vm._isVue = true
    // merge options
    // 是否子组件 非根组件 非 new Vue(options) 
    /*
      new Vue({
        el: '#app',
        data() {
          return ...
        }
      })
    */
    if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else {
      // 根组件 
      // 合并全局配置到根组件上
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }
    /* istanbul ignore else */
    if (process.env.NODE_ENV !== 'production') {
      // 新增 vm._renderProxy
      initProxy(vm)
    } else {
      vm._renderProxy = vm
    }
    // expose real self
    vm._self = vm
    // 初始化组件实例属性 $parent $children $refs $root
    initLifecycle(vm)
    // 注册组件上的事件 
    initEvents(vm)
    // $slots $createElement 
    // 通过 defineReactive 添加 $attrs $listeners
    initRender(vm)
    // 执行生命周期 beforeCreate 
    callHook(vm, 'beforeCreate')
    // 解析 inject 配置项 将配置项 key 添加到 vm 上 并做响应式处理
    initInjections(vm) // resolve injections before data/props
    // 处理 props data method watch computed 
    initState(vm)
    // 将配置的 provide 添加到 vm
    initProvide(vm) // resolve provide after data/props
    // 调用生命周期 created 方法
    callHook(vm, 'created')

    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      vm._name = formatComponentName(vm, false)
      mark(endTag)
      measure(`vue ${vm._name} init`, startTag, endTag)
    }

    // 如果有 el 默认执行 $mount 挂载
    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80